/**
 *  Copyright 2011 Marco Berri - marcoberri@gmail.com
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and limitations under the License.
 **/
package com.mbfasttrack.service;

import com.mbfasttrack.model.Geonames;
import com.mbfasttrack.utils.BigFile;
import com.mbfasttrack.utils.Default;
import com.mbfasttrack.utils.HttpUtil;
import com.mbfasttrack.utils.ZipUtil;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.geo.Distance;
import org.springframework.data.mongodb.core.geo.Metrics;
import org.springframework.data.mongodb.core.index.GeospatialIndex;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.util.WebUtils;

/**
 * @author Marco Berri marcoberri@gmail.com http://tecnicume.blogspot.com
 */
@Service("GeonamesService")
@Transactional
public class GeonamesService extends Base {

    /**
     * //TO DO il sort
     * @param like
     * @return
     */
    public List<Geonames> getAllByLikeLoc(String like) {
        //{"demonloc": { $regex : 'san*', $options: 'i' } }
        //{"alternatenames": { $regex : ".*santhi.*", $options: "i" } }
        //.sort().on("asciiname", Order.ASCENDING)
        return mongoTemplate.find(
                new Query(
                Criteria.where("asciiname").regex(".*" + like + ".*", "i").
                orOperator(
                Criteria.where("alternatenames").regex(".*" + like + ".*", "i")).andOperator(
                Criteria.where("featureclass").is("P"))).limit(10), Geonames.class);
    }

    /**
     * 
     * @param file 
     * @return
     */
    public boolean importFromFile(String file) {

        try {


            File f = new File(file);

            if (!f.exists()) {
                System.err.println("file name to import:" + f + " not exists");
                return false;
            }



            BigFile bigfile = new BigFile(f.toString());

            int i = 1;
            for (String line : bigfile) {

                String[] token = line.split("\t");
                if (!token[8].equalsIgnoreCase("IT")) {
                    continue;
                }

                Geonames geo = new Geonames();
                geo.setGeonameid(Default.toInteger(token[0]));
                geo.setName(Default.toString(token[1]));
                geo.setAsciiname(Default.toString(token[2]));
                geo.setAlternatenames(Default.toString(token[3]));
                geo.setFeatureclass(Default.toString(token[6]));
                geo.setFeaturecode(Default.toString(token[7]));
                geo.setCountrycode(Default.toString(token[8]));
                geo.setCc2(Default.toString(token[9]));
                geo.setAdmin1(Default.toString(token[10]));
                geo.setAdmin2(Default.toString(token[11]));
                geo.setAdmin3(Default.toString(token[12]));
                geo.setAdmin4(Default.toString(token[13]));
                geo.setPopulation(Default.toInteger(token[14]));
                geo.setElevation(Default.toInteger(token[15]));

                geo.setLatitude(Default.toDouble(token[4]));
                geo.setLongitude(Default.toDouble(token[5]));

                Double[] latlon = {Default.toDouble(token[4]), Default.toDouble(token[5])};
                geo.setLatlon(latlon);


                /*
                dem               : digital elevation model, srtm3 or gtopo30, average elevation of 3''x3'' (ca 90mx90m) or 30''x30'' (ca 900mx900m) area in meters, integer
                timezone          : the timezone id (see file timeZone.txt)
                modification date
                 */

                geonamesRepository.save(geo);

                i++;

            }

            System.err.println("tot import :" + i);
            log.debug("tot import geonames:" + i);

            mongoTemplate.indexOps(Geonames.class).ensureIndex(new GeospatialIndex("latlon"));

        } catch (Exception e) {
            log.fatal(e);
            System.out.println("fatal:" + e.getMessage());
        }


        return true;
    }

    /**
     * 
     * @param x
     * @param y
     * @param km
     * @return
     */
    public Page<Geonames> getAllNear(Double x, Double y, Integer km) {



        org.springframework.data.mongodb.core.geo.Point p = new org.springframework.data.mongodb.core.geo.Point(x, y);
        Distance distance = new Distance(km, Metrics.KILOMETERS);

        try {
            return geonamesRepository.findByLatlonNear(p, distance, new PageRequest(0, 10));

        } catch (Exception e) {
            log.fatal(e);
        }
        return null;

    }

    public void importData(String sys_geonames_url) {

        //temporary folder
        File tmp_dir = WebUtils.getTempDir(this.context);
        tmp_dir = new File(tmp_dir.toString() + "/tmp/");

        String tmp_file_name = "/tmp_geonames.zip";

        try {
            FileUtils.forceMkdir(tmp_dir);
        } catch (Exception e) {
            System.err.println("MakeDir Fails");
        }

        System.err.println("Temporary Dir:" + tmp_dir);
        System.err.println("Start Download Url:" + sys_geonames_url);

        tmp_file_name = tmp_dir.toString() + tmp_file_name;

        HttpUtil.downloadData(sys_geonames_url, tmp_file_name);
        ArrayList<String> list = null;
        try {
            list = ZipUtil.unzip(new File(tmp_file_name), tmp_dir.toString());

            for (String file : list) {
                System.err.println("File unzip : " + file);
            }


        } catch (IOException ex) {
            System.err.println("Error " + ex.getMessage());
        }

        System.err.println("Unzip File on : " + tmp_dir.toString());

        this.geonamesRepository.deleteAll();

        File to_import = new File(list.get(0));
        this.importFromFile(to_import.toString());

        //elimino i due file scaricati
        boolean delete = to_import.delete();
        System.err.println("Delete file  " + to_import + " - status: " + delete);

        delete = new File(tmp_file_name).delete();
        System.err.println("Delete file  " + tmp_file_name + " - status: " + delete);


    }
}
